package org.lease.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.lease.common.exception.BizException;
import org.lease.common.result.Result;
import org.lease.mapper.ApartmentInfoMapper;
import org.lease.mapper.GraphInfoMapper;
import org.lease.mapper.LabelInfoMapper;
import org.lease.mapper.RoomInfoMapper;
import org.lease.model.entity.*;
import org.lease.model.enums.ItemType;
import org.lease.model.vo.*;
import org.lease.service.*;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class ApartmentInfoServiceImpl extends ServiceImpl<ApartmentInfoMapper, ApartmentInfo> implements ApartmentInfoService {
    @Lazy
    @Autowired
    private RoomInfoService roomInfoService;
    @Lazy
    @Autowired
    private LeaseAgreementService leaseAgreementService;

    @Autowired
    private GraphInfoService graphInfoService;
    @Autowired
    private ApartmentFacilityService apartmentFacilityService;
    @Autowired
    private ApartmentLabelService apartmentLabelService;
    @Autowired
    private ApartmentFeeValueService apartmentFeeValueService;

    @Autowired
    private LabelInfoMapper labelInfoMapper;
    @Autowired
    private GraphInfoMapper graphInfoMapper;
    @Autowired
    private RoomInfoMapper roomInfoMapper;

    // 分页条件查询公寓信息
    @Override
    public IPage<ApartmentItemVo> pageQuery(IPage<ApartmentItemVo> page, ApartmentQueryVo queryVo) {
        // 分页条件查询公寓列表
        Page<ApartmentInfo> apartmentInfoPage = new Page<>(page.getCurrent(), page.getSize());
        LambdaQueryWrapper<ApartmentInfo> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(queryVo.getProvinceId() != null, ApartmentInfo::getProvinceId, queryVo.getProvinceId());
        wrapper.eq(queryVo.getCityId() != null, ApartmentInfo::getCityId, queryVo.getCityId());
        wrapper.eq(queryVo.getDistrictId() != null, ApartmentInfo::getDistrictId, queryVo.getDistrictId());
        page(apartmentInfoPage, wrapper);
        BeanUtils.copyProperties(apartmentInfoPage, page);
        // 遍历统计每个公寓下的房间信息
        ArrayList<ApartmentItemVo> apartmentItemVos = new ArrayList<>();
        apartmentInfoPage.getRecords().forEach(ApartmentInfo -> {
            Long apartmentId = ApartmentInfo.getId();
            // 公寓下的房间总数
            Long roomCount = roomInfoService.countReleasedByApartmentId(apartmentId);
            // 公寓下的在租房间数
            Long leaseCount = leaseAgreementService.countLeasedByApartmentId(apartmentId);
            // 计算可用房间数
            long availableCount = roomCount - leaseCount;
            // 封装数据
            ApartmentItemVo apartmentItemVo = new ApartmentItemVo();
            BeanUtils.copyProperties(ApartmentInfo, apartmentItemVo);
            apartmentItemVo.setTotalRoomCount(roomCount);
            apartmentItemVo.setFreeRoomCount(availableCount);
            apartmentItemVos.add(apartmentItemVo);
        });
        page.setRecords(apartmentItemVos);

        return page;
    }

    // 保存或更新公寓信息
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveOrUpdateApartment(ApartmentSubmitVo apartmentSubmitVo) {
        boolean isUpdate = apartmentSubmitVo.getId() != null;

        // 保存或更新公寓自身信息
        saveOrUpdate(apartmentSubmitVo);

        // 判断是否为更新操作
        if (isUpdate) {
            this.removeApartmentRelations(apartmentSubmitVo.getId());
        }

        // 保存公寓关联的图片
        List<GraphVo> graphVoList = apartmentSubmitVo.getGraphVoList();
        if (!CollectionUtils.isEmpty(graphVoList)) {
            ArrayList<GraphInfo> graphInfoList = new ArrayList<>();
            for (GraphVo graphVo : graphVoList) {
                GraphInfo graphInfo = new GraphInfo();
                graphInfo.setItemType(ItemType.APARTMENT);
                graphInfo.setItemId(apartmentSubmitVo.getId());
                graphInfo.setName(graphVo.getName());
                graphInfo.setUrl(graphVo.getUrl());
                graphInfoList.add(graphInfo);
            }
            graphInfoService.saveBatch(graphInfoList);
        }

        // 保存公寓关联的配套信息
        List<Long> facilityInfoIdList = apartmentSubmitVo.getFacilityInfoIds();
        if (!CollectionUtils.isEmpty(facilityInfoIdList)) {
            ArrayList<ApartmentFacility> facilityList = new ArrayList<>();
            for (Long facilityId : facilityInfoIdList) {
                ApartmentFacility apartmentFacility = new ApartmentFacility();
                apartmentFacility.setApartmentId(apartmentSubmitVo.getId());
                apartmentFacility.setFacilityId(facilityId);
                facilityList.add(apartmentFacility);
            }
            apartmentFacilityService.saveBatch(facilityList);
        }

        // 保存公寓关联的标签信息
        List<Long> labelIds = apartmentSubmitVo.getLabelIds();
        if (!CollectionUtils.isEmpty(labelIds)) {
            List<ApartmentLabel> apartmentLabelList = new ArrayList<>();
            for (Long labelId : labelIds) {
                ApartmentLabel apartmentLabel = new ApartmentLabel();
                apartmentLabel.setApartmentId(apartmentSubmitVo.getId());
                apartmentLabel.setLabelId(labelId);
                apartmentLabelList.add(apartmentLabel);
            }
            apartmentLabelService.saveBatch(apartmentLabelList);
        }

        // 保存公寓关联的杂费信息
        List<Long> feeValueIds = apartmentSubmitVo.getFeeValueIds();
        if (!CollectionUtils.isEmpty(feeValueIds)) {
            ArrayList<ApartmentFeeValue> apartmentFeeValueList = new ArrayList<>();
            for (Long feeValueId : feeValueIds) {
                ApartmentFeeValue apartmentFeeValue = new ApartmentFeeValue();
                apartmentFeeValue.setApartmentId(apartmentSubmitVo.getId());
                apartmentFeeValue.setFeeValueId(feeValueId);
                apartmentFeeValueList.add(apartmentFeeValue);
            }
            apartmentFeeValueService.saveBatch(apartmentFeeValueList);

        }
    }

    // 根据 ID 查询公寓信息
    @Override
    public ApartmentDetailVo getApartmentDetailById(Long id) {
        // 查询公寓基本信息
        ApartmentInfo apartmentInfo = this.getById(id);
        if (apartmentInfo == null) {
            return null;
        }

        // 查询关联的配套信息
        List<FacilityInfo> facilityInfoList = apartmentFacilityService.listWithFacilityInfo(id);
        // 查询关联的标签信息
        List<LabelInfo> labelInfoList = apartmentLabelService.listWithLabelInfo(id);
        // 查询关联的杂费信息
        List<FeeValueVo> feeValueVoList = apartmentFeeValueService.listWithFeeValueVo(id);
        // 查询关联的图片
        LambdaQueryWrapper<GraphInfo> graphInfoLambdaQueryWrapper = new LambdaQueryWrapper<>();
        graphInfoLambdaQueryWrapper.eq(GraphInfo::getItemId, id);
        graphInfoLambdaQueryWrapper.eq(GraphInfo::getItemType, ItemType.APARTMENT);
        List<GraphInfo> graphInfoList = graphInfoService.list(graphInfoLambdaQueryWrapper);
        List<GraphVo> graphVoList = graphInfoList.stream().map(graphInfo -> {
            GraphVo graphVo = new GraphVo();
            BeanUtils.copyProperties(graphInfo, graphVo);
            return graphVo;
        }).collect(Collectors.toList());


        // 类型转换
        ApartmentDetailVo apartmentDetailVo = new ApartmentDetailVo();
        BeanUtils.copyProperties(apartmentInfo, apartmentDetailVo);
        apartmentDetailVo.setFacilityInfoList(facilityInfoList);
        apartmentDetailVo.setLabelInfoList(labelInfoList);
        apartmentDetailVo.setFeeValueVoList(feeValueVoList);
        apartmentDetailVo.setGraphVoList(graphVoList);

        return apartmentDetailVo;
    }

    // 根据 ID 删除公寓信息
    @Override
    public void removeApartmentById(Long id) {
        LambdaQueryWrapper<RoomInfo> roomInfoLambdaQueryWrapper = new LambdaQueryWrapper<>();
        roomInfoLambdaQueryWrapper.eq(RoomInfo::getApartmentId, id);
        long total = roomInfoService.count(roomInfoLambdaQueryWrapper);
        if (total > 0) {
            throw new BizException("房间数大于0，无法删除公寓");
        }

        this.removeApartmentRelations(id);
        this.removeById(id);
    }

    @Override
    public ApartmentItemVo selectApartmentItemVoById(Long id) {
        ApartmentInfo apartmentInfo = baseMapper.selectById(id);

        List<LabelInfo> labelInfoList = labelInfoMapper.selectListByApartmentId(id);

        List<GraphVo> graphVoList = graphInfoMapper.selectListByItemTypeAndId(ItemType.APARTMENT, id);

        BigDecimal minRent = roomInfoMapper.selectMinRentByApartmentId(id);

        ApartmentItemVo apartmentItemVo = new ApartmentItemVo();
        BeanUtils.copyProperties(apartmentInfo, apartmentItemVo);

        apartmentItemVo.setGraphVoList(graphVoList);
        apartmentItemVo.setLabelInfoList(labelInfoList);
        apartmentItemVo.setMinRent(minRent);
        return apartmentItemVo;
    }

    private void removeApartmentRelations(Long apartmentId) {
        // 删除原先关联的图片
        LambdaQueryWrapper<GraphInfo> graphQueryWrapper = new LambdaQueryWrapper<>();
        graphQueryWrapper.eq(GraphInfo::getItemType, ItemType.APARTMENT); // 公寓类型的图片
        graphQueryWrapper.eq(GraphInfo::getItemId, apartmentId); // 该公寓关联的图片
        graphInfoService.remove(graphQueryWrapper);
        // 删除原先关联的配套信息
        LambdaQueryWrapper<ApartmentFacility> facilityQueryWrapper = new LambdaQueryWrapper<>();
        facilityQueryWrapper.eq(ApartmentFacility::getApartmentId, apartmentId);
        apartmentFacilityService.remove(facilityQueryWrapper);
        // 删除原先关联的标签信息
        LambdaQueryWrapper<ApartmentLabel> labelQueryWrapper = new LambdaQueryWrapper<>();
        labelQueryWrapper.eq(ApartmentLabel::getApartmentId, apartmentId);
        apartmentLabelService.remove(labelQueryWrapper);
        // 删除原先关联的杂费信息
        LambdaQueryWrapper<ApartmentFeeValue> feeQueryWrapper = new LambdaQueryWrapper<>();
        feeQueryWrapper.eq(ApartmentFeeValue::getApartmentId, apartmentId);
        apartmentFeeValueService.remove(feeQueryWrapper);
    }
}
